use honeybee::mongodb::bson;
use honeybee::prelude::*;
use honeybee::Result;

use crate::users;

#[derive(Default)]
pub struct UmsgActor {
    users_addr: Option<Addr<users::Users>>,
}

impl UmsgActor {
    fn users_addr(&self) -> &Addr<users::Users> {
        self.users_addr.as_ref().unwrap()
    }
}

impl Service for UmsgActor {}

#[async_trait::async_trait]
impl Actor for UmsgActor {
    fn name(&self) -> &str {
        "UmsgActor"
    }

    async fn started(&mut self, ctx: &mut Context<Self>) -> Result<()> {
        info!("{} started", self.name());
        let router = ctx.get_router().await?;
        router.register::<proto::UmsgForward>();

        let actor_center = ActorCenter::from_registry().await?;
        self.users_addr = actor_center.call(Query::new("Users")).await?.into();
        Ok(())
    }

    async fn stopped(&mut self, _ctx: &mut Context<Self>) {
        info!("{} stoped", self.name());
    }
}

#[async_trait::async_trait]
impl Handler<NetMsg<proto::UmsgForward>> for UmsgActor {
    async fn handle(
        &mut self,
        _ctx: &mut Context<Self>,
        msg: NetMsg<proto::UmsgForward>,
    ) -> Result<()> {
        let msg = msg.msg;
        let msg_doc = bson::Document::from_reader(&mut msg.msg_bytes.as_slice())?;
        let object_id = umsg_db::insert(msg.uid, msg.msg_type, msg_doc.clone()).await?;
        info!(
            "insert umsg uid:{} object_id:{} type:{:?} msg:{} success",
            msg.uid, object_id, msg.msg_type, msg_doc
        );
        let _ = self.users_addr().send(users::UmsgNotify {
            uid: msg.uid,
            object_id: object_id.to_hex(),
            msg_type: msg.msg_type,
            msg_bytes: msg.msg_bytes,
        });
        Ok(())
    }
}
